package com.darren.euc.action.app;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.darren.euc.entity.*;
import com.darren.euc.repository.MeetingroomOrderRepository;
import com.darren.euc.service.MeetingroomOrderService;
import com.darren.euc.service.MeetingroomService;
import com.darren.euc.util.DateUtil;
import com.darren.euc.util.LocalCacheUtil;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import org.apache.log4j.Logger;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import static com.darren.euc.util.GenegateDomainUtil.isAvaliable;

/**
 * Created by jianc at 2018/3/12 0:31.
 */
@Controller
@RequestMapping("/_meetingroom")
public class _MeetingroomAction {

	
	private static final SimpleDateFormat FORMATTER = new SimpleDateFormat("yyyyMMdd");
    private static final Logger log = Logger.getLogger(_MeetingroomAction.class);
    private static LoadingCache<Object, Object> cache = CacheBuilder.newBuilder().maximumSize(1000)
            .expireAfterWrite(60, TimeUnit.SECONDS).recordStats().build(new CacheLoader<Object, Object>() {
                @Override
                public Object load(Object key) throws Exception {
                    return key;
                }
            });
    @Autowired
    private MeetingroomService meetingroomService;
    @Autowired
    private MeetingroomOrderService meetingroomOrderService;
    @Autowired
    private MeetingroomOrderRepository meetingroomOrderRepository;

    public static Object get(Object key) throws ExecutionException {
        Object var = cache.get(key);
        if (var.equals(key)) {
            return null;
        } else {
            return cache.get(key);
        }
    }

    public static void put(Object key, Object value) {
        cache.put(key, value);
    }

    /**
     * 会议室当前会议与下一会议
     */
    @ResponseBody
    @RequestMapping(value = "/currentmeeting")
    public ResponseJSON currentMeeting(@RequestParam(name = "room_id") Integer roomId) {
        MeetingDataVO meetingDataVO = meetingroomOrderService.findDataByRoomId(roomId);
        return new ResponseJSON().setData(meetingDataVO);
    }


    /**
     * 会议室列表
     */
    @ResponseBody
    @RequestMapping(value = "/meetingroomList")
    public ResponseJSON meetingroomList(@RequestParam(name = "space_id", required = false) Integer spaceId,
            @RequestParam(name = "pn", required = false, defaultValue = "1") Integer pn,
            @RequestParam(name = "ps", required = false, defaultValue = "10") Integer ps) {
        PageBean pageBean = meetingroomService.queryForPageSpaceIdHQL(spaceId, ps, pn);
        return new ResponseJSON().setData(pageBean);
    }

    /**
     * 会议室详情
     */
    @ResponseBody
    @RequestMapping(value = "/meetingroomDetail")
    public ResponseJSON meetingroomDetail(@RequestParam(name = "meetingroom_id") Integer meetingroomId,
            @RequestParam(name = "date_time") String dateTime) {
        Meetingroom meetingroom = meetingroomService.findById(meetingroomId);
        List<Integer> statuses = Lists.newArrayList(1);// 只选择未开始的，进行中或者已结束的不要
        List<MeetingroomOrder> meetingroomOrderList = meetingroomOrderService
                .findByRoomIdAndDayAndStatusInAndPayStatusNot(meetingroomId, new DateTime(dateTime).toDate(), statuses, 0);//还要不是已取消的
        List<BookTimeRange> all = Lists.newArrayList();
        for (MeetingroomOrder meetingroomOrder : meetingroomOrderList) {
            all.addAll(JSONArray.parseArray(meetingroomOrder.getRangeList(), BookTimeRange.class));
        }
        //增加进行中 start
        List<Integer> statuses3 = Lists.newArrayList(3);// 只选择进行中
        List<MeetingroomOrder> meetingroomOrderList3 = meetingroomOrderService
                .findByRoomIdAndDayAndStatusInAndPayStatusNot(meetingroomId, new DateTime(dateTime).toDate(), statuses3, 0);//还要不是已取消的
        List<BookTimeRange> all3 = Lists.newArrayList();
        for (MeetingroomOrder meetingroomOrder : meetingroomOrderList3) {
            all3.addAll(JSONArray.parseArray(meetingroomOrder.getRangeList(), BookTimeRange.class));
        }
        List<String> times3 = all3.stream().map(BookTimeRange::getTime).collect(Collectors.toList());
        //增加进行中 end
        
        MeetingroomVO meetingroomVO = new MeetingroomVO(meetingroom);
        List<BookTimeRange> rangeList = DateUtil.gene(meetingroom.getBookStartTime(), meetingroom.getBookEndTime());
        List<String> times = all.stream().map(BookTimeRange::getTime).collect(Collectors.toList());
        times.addAll(times3);//合并集合
        for (BookTimeRange bookTimeRange : rangeList) {
            String time = dateTime + " " + bookTimeRange.getTime() + ":00";
            Date timeDate = DateUtil.string2Date(time, "yyyy-MM-dd HH:mm:ss");
            if (times.contains(bookTimeRange.getTime()) || timeDate.before(new Date())) {
                bookTimeRange.setStatus(1);
            }
        }
        BookTimeRange endOne = new BookTimeRange();
        BookTimeRange subEndOne = rangeList.get(rangeList.size()-1);
        endOne.setId(subEndOne.getId()+1);
        endOne.setStatus(subEndOne.getStatus()==1?1:0);
        endOne.setTime(DateUtil.addHalfHour(subEndOne.getTime()));
        rangeList.add(endOne);
        meetingroomVO.setRangeList(rangeList);
        return new ResponseJSON().setData(meetingroomVO);
    }

    /**
     * 会议取消，与再次预定 1再次预定 0 取消预定
     */
    @ResponseBody
    @RequestMapping(value = "/updateMeetingOrderStatus")
    public ResponseJSON updateMeetingOrderStatus(@RequestParam(name = "order_id") Integer orderId,
            @RequestParam(name = "status") Integer payStatus) {
        MeetingroomOrder meetingroomOrder = meetingroomOrderRepository.findOne(orderId);
        meetingroomOrder.setPayStatus(payStatus);
        List<BookTimeRange> bookTimeRanges = JSONArray.parseArray(meetingroomOrder.getRangeList(), BookTimeRange.class);
        if (CollectionUtils.isEmpty(bookTimeRanges)){
            return new ResponseJSON(-3,"订单异常",null);
        }
        if (payStatus == 0){
            String dateTime = DateUtil.dateToStr(meetingroomOrder.getDay(),"yyyy-MM-dd") + " " + bookTimeRanges.get(0).getTime()+":00";
            Date bookTimeBegin = DateUtil.string2Date(dateTime,"yyyy-MM-dd HH:mm:ss");
            if (new DateTime(bookTimeBegin).minusHours(2).isBefore(new DateTime())) {
                return new ResponseJSON(-1, "禁止取消", null);
            }
        }else if (payStatus == 1){
            return new ResponseJSON(-4, "请返回会议室列表重新预订", null);
        }
        meetingroomOrder.setUpdateTime(new Date());
        return new ResponseJSON().setData(meetingroomOrderRepository.save(meetingroomOrder));
    }

    /**
     * 会议状态更新， 1仅预定 2 已支付
     */
    @ResponseBody
    @RequestMapping(value = "/updateMeetingOrderPayStatus")
    public ResponseJSON updateMeetingOrderPayStatus(@RequestParam(name = "order_id") Integer orderId,
                                                 @RequestParam(name = "pay_status") Integer payStatus) {
        LocalCacheUtil.put("pay_status", payStatus <= 0 ? -1 :payStatus);
        MeetingroomOrder meetingroomOrder = meetingroomOrderRepository.findOne(orderId);
        meetingroomOrder.setPayStatus(payStatus);
        meetingroomOrder.setUpdateTime(new Date());
        return new ResponseJSON().setData(meetingroomOrderRepository.save(meetingroomOrder));
    }

    /**
     * 会议室预订
     */
    @ResponseBody
    @RequestMapping(value = "/meetingroomOrderSave")
    public ResponseJSON meetingroomOrderSave(@RequestParam(name = "meetingroom_id") Integer meetingroomId,
            @RequestParam(name = "date_time") String dateTime, @RequestParam(name = "range_id_list") String rangeIdList,
            @RequestParam(name = "mem_list") String memList, @RequestParam(name = "money") String money,
            @RequestParam(name = "subject") String subject, HttpServletRequest request) {
        Member member = (Member) request.getAttribute("member");
        Integer memberId = member.getId();
        MeetingroomOrder meetingroomOrder = new MeetingroomOrder();
        meetingroomOrder.setRoomId(meetingroomId);
        meetingroomOrder.setMemberId(memberId);
        if (new DateTime(dateTime).isBefore(new DateTime().minusDays(1)) || !isAvaliable()) {
            return new ResponseJSON(-4, "不可预定时段", null);
        }
        meetingroomOrder.setDay(new DateTime(dateTime).toDate());
        List<BookTimeRange> rangeList = Lists.newArrayList();
        Meetingroom meetingroom = meetingroomService.findById(meetingroomId);
        List<BookTimeRange> bookTimeRangeList = DateUtil.gene(meetingroom.getBookStartTime(),
                meetingroom.getBookEndTime());

        if (JSONArray.parseArray(rangeIdList).toArray().length == 0) {
            return new ResponseJSON(-5, "请选择预定时间", null);
        }
        List<String> newBookTimes = Lists.newArrayList();
        Object[] idObj = JSONArray.parseArray(rangeIdList).toArray();
        for (Object idStr : idObj){
            Integer id = (Integer) idStr;
            Optional<BookTimeRange> bookTimeRangeOptional = bookTimeRangeList.stream().filter(item->item.getId().equals(id)).findFirst();
            newBookTimes.add(bookTimeRangeOptional.isPresent()?bookTimeRangeOptional.get().getTime():null);
        }
        Set<Integer> memIds;
        try {
            memIds = Sets.newHashSet(JSONArray.parseArray(memList, Integer.class));
        } catch (Exception e) {
            return new ResponseJSON(-3, "选定与会人员数据异常", null);
        }

        synchronized (dateTime.intern()) {
            List<Integer> statuses = Lists.newArrayList(1,3);// 只选择未开始的和进行中，而已结束的不要
            List<MeetingroomOrder> meetingroomOrderList = meetingroomOrderService
                    .findByRoomIdAndDayAndStatusInAndPayStatusNot(meetingroomId, new DateTime(dateTime).toDate(), statuses,0);//已取消的排除
            List<BookTimeRange> all = Lists.newArrayList();
            for (MeetingroomOrder order : meetingroomOrderList) {
                all.addAll(JSONArray.parseArray(order.getRangeList(), BookTimeRange.class));
            }
            List<String> timed = all.stream().map(BookTimeRange::getTime).collect(Collectors.toList());
            Integer id = 0;
            try {
                for (String time : newBookTimes) {
                    BookTimeRange bookTimeRange = new BookTimeRange();
                    bookTimeRange.setId((Integer) idObj[id++]);
                    Date timeDate = DateUtil.string2Date(dateTime + " " + time + ":00","yyyy-MM-dd HH:mm:ss");
                    if (timeDate.before(new Date()) || timed.contains(time)) {
                        return new ResponseJSON(-4, "不可预定时段", null);
                    }
                    bookTimeRange.setTime(time);
                    bookTimeRange.setStatus(1);
                    rangeList.add(bookTimeRange);
                }
            }catch (IndexOutOfBoundsException ioobe){
                return new ResponseJSON(-6, "参数异常", null);
            }
            meetingroomOrder.setRangeList(JSONObject.toJSONString(rangeList));
            meetingroomOrder.setMemList(JSONArray.toJSONString(memIds));
            meetingroomOrder.setSpaceId(member.getSpaceId());
            meetingroomOrder.setMoney(new BigDecimal(money));
            meetingroomOrder.setStatus(1);// 未开始
            meetingroomOrder.setPayStatus(1); // 未支付
            meetingroomOrder.setCreateTime(new Date());
            meetingroomOrder.setUpdateTime(new Date());
            meetingroomOrder.setSubject(subject);
            MeetingroomOrder meetingroomOrder1 = meetingroomOrderService.save(meetingroomOrder);
            meetingroomOrder1.setOrderCode(generateOrderNumber(meetingroomOrderService.getCurrentDayCount(meetingroomOrder1.getOrderId())));
            meetingroomOrderService.save(meetingroomOrder1);
        }
        return new ResponseJSON();
    }
    
    private String generateOrderNumber(BigInteger orderNumber){
		Date currentTime = new Date();
		return "M" + FORMATTER.format(currentTime) + String.format("%03d", orderNumber);
	}

}